package com.hua.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.util.concurrent.AtomicDouble;
import com.hua.common.ResponseCode;
import com.hua.domain.Orders;
import com.hua.domain.StoreInfo;
import com.hua.domain.domainVo.IncomeResponse;
import com.hua.exception.BusinessException;
import com.hua.mapper.OrdersMapper;
import com.hua.mapper.StoreInfoMapper;
import com.hua.service.StoreInfoService;
import com.hua.util.JSONUtils;
import com.hua.util.RedisCache;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.hua.constant.RedisConstant.REDIS_STORE_KEY;
import static java.math.BigDecimal.valueOf;

/**
 * @author cl
 * @description 针对表【store_info】的数据库操作Service实现
 * @createDate 2022-10-19 11:19:07
 */
@Service
public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo>
        implements StoreInfoService {

    private byte restartTimes = 0;

    @Resource
    private OrdersMapper ordersMapper;

    /**
     * 商店相关的mapper
     */
    @Resource
    private StoreInfoMapper storeInfoMapper;

    /**
     * redis的工具
     */
    @Resource
    private RedisCache redisCache;

    /***根据店铺的id查询店铺的所有信息
     * @param storeId 店铺的id
     * @return 店铺的实体对象
     * */
    @Override
    public StoreInfo getStoreInfo(Integer storeId) {
        final String errorDescription =   "获取店铺信息失败";

        String key = REDIS_STORE_KEY + storeId;
        String storeInfoJson = redisCache.getCacheObject(key); //从缓存中查询店铺
        //如果缓存中有数据就直接返回
        if (storeInfoJson != null && !"".equals(storeInfoJson)) {
            return JSONUtils.jsonToObj(storeInfoJson, StoreInfo.class);
        }
        //如果storeId是空就跑出异常信息
        if (storeId == null) {
            throw new BusinessException(ResponseCode.PARAMS_ERROR,errorDescription);
        }
        //根据店铺id查询店铺
        StoreInfo storeInfo = storeInfoMapper.getStoreInfo(storeId);

        //防止查询店铺信息是空
        if (storeInfo == null) {
            throw new BusinessException(ResponseCode.PARAMS_NULL_ERROR, errorDescription);
        }
        //把数据存入数据库
        redisCache.setCacheObject(key, JSONUtils.toJsonStr(storeInfo),30, TimeUnit.MINUTES);

        //返回我们需要的商铺信息
        return getStoreInfo(storeInfo);
    }

    /**
     * 查询店铺的金额信息
     *
     * @param storeId 店铺id
     * @return 店铺的返回对象
     */
    @Override
    public IncomeResponse getIncomeInfo(Integer storeId) {
        //根据店铺的id查询店铺
        final String key = REDIS_STORE_KEY + storeId;
        //获取存储的storeJson格式
        String storeInfoJson = redisCache.getCacheObject(key);
        //把json转换成我们需要的对象
        StoreInfo storeInfo = JSONUtils.jsonToObj(storeInfoJson, StoreInfo.class);
        //如果redis 查不到就去查数据库
        if(storeInfo == null) {
            storeInfo = storeInfoMapper.getStoreInfo(storeId);
        }
        //防止storeInfo是空
        if (storeInfo == null) {
            throw new BusinessException(ResponseCode.PARAMS_NULL_ERROR, "获取店铺信息失败");
        }
        //查询店铺的流水
        Long income = storeInfo.getIncome(); // 店铺的总收入
        BigDecimal dayIncome = storeInfo.getDayIncome(); //店铺的日收入
        String storeName = storeInfo.getStoreName();    //店铺的日收入
        Integer id = storeInfo.getStoreId();  //店铺的id
        Long lastYI = storeInfo.getLastYI();    //店铺去年的收入
        Long lastMonthSV = storeInfo.getLastMonthSV(); //上个月售卖出去的量
        Long lastMI = storeInfo.getLastMonthIncome(); //店铺上个月的收入
        Long saleVolume = storeInfo.getSaleVolume(); //店铺上个月的售卖量
        String storeImg = storeInfo.getStoreImg(); //店铺的storeImg

        /*设置对应的信息*/
        IncomeResponse incomeResponse = new IncomeResponse();
        incomeResponse.setId(id);
        incomeResponse.setStoreName(storeName);
        incomeResponse.setDayIncome(dayIncome);
        incomeResponse.setIncome(income);
        incomeResponse.setLastMonthIncome(lastMI);
        incomeResponse.setLastYI(lastYI);
        incomeResponse.setSaleVolume(saleVolume);
        incomeResponse.setLastMonthSV(lastMonthSV);
        incomeResponse.setStoreImg(storeImg);

        return incomeResponse;

    }

    /**
     * 让商店下架
     * @param inBusiness 商店是否逻辑删除
     * @param storeId 商店的id
     * @return 商店的完整信息
     */
    @Override
    @Transactional
    public Boolean storeOffOnline(Integer inBusiness, Integer storeId) {
        final String key = REDIS_STORE_KEY + storeId;
        //防止storeId是否为空
        if (storeId == null){
            throw new BusinessException(ResponseCode.PARAMS_ERROR,"下架商店失败");
        }
        //商店下架
        int updateCount = storeInfoMapper.storeOffOnline(inBusiness, storeId);
        if (updateCount > 0) {
                redisCache.deleteObject(key);
        }
        return Boolean.TRUE.equals(updateCount == 1);
    }

    /**
     * 让商店下架
     *
     * @param isDelete 商店是否关门 -- isDelete 1-关门
     * @param storeId  商店的id
     * @return 商店的完整信息
     */
    @Override
    @Transactional
    public Boolean storeDown(Integer isDelete, Integer storeId) {
        final String key = REDIS_STORE_KEY + storeId;
        if(isDelete == null || storeId == null){
            throw new BusinessException(ResponseCode.PARAMS_NULL_ERROR,"商店下架失败 请稍后再试!");
        }
        //下架商店
        int isDown = storeInfoMapper.storeDown(isDelete, storeId);
        if(isDown >= 0){
            redisCache.deleteObject(key);
        }
        //转换成我们需要的值
        return Boolean.TRUE.equals(isDown == 1);
    }

    /**
     * 更新商店的所有信息
     *
     * @param storeInfo 商店的实体类
     * @return boolean 更新是否成功
     */
    @Override
    @Transactional
    public Boolean updateStoreInfo(StoreInfo storeInfo) {
        //填写主键相同
        LambdaUpdateWrapper<StoreInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(StoreInfo::getStoreId, storeInfo.getStoreId());
        //尝试更新数据
        int update = storeInfoMapper.update(storeInfo, updateWrapper);
        if(update > 0){
            redisCache.deleteObject(REDIS_STORE_KEY + storeInfo.getStoreId());
        }
        return Boolean.TRUE.equals(update > 0);
    }

    /**
     * 定时的获取商店的月收入
     */
    @Override
    @Transactional
    public void updateStoreLastMonthIncome() {
        AtomicDouble count = new AtomicDouble();
        System.out.println(ordersMapper);
        //获取上个月数据
        List<Orders> orders = ordersMapper.selectLast();
        orders.forEach(order -> count.addAndGet(order.getPayedPrice().doubleValue()));
        LambdaUpdateWrapper<StoreInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(StoreInfo::getLastMonthIncome, valueOf(count.doubleValue()));
        updateWrapper.eq(StoreInfo::getStoreId, 1);
        boolean update = this.update(updateWrapper);
        if(update)
            redisCache.deleteObject(REDIS_STORE_KEY + "1");
        if(!update && restartTimes++ < 3)
            updateStoreLastMonthIncome();
    }

    /***获得安全的StoreInfo对象*/
    private StoreInfo getStoreInfo(@NotNull StoreInfo originalStoreInfo) {
        StoreInfo storeInfo = new StoreInfo();
        storeInfo.setStoreId(originalStoreInfo.getStoreId());
        storeInfo.setStoreName(originalStoreInfo.getStoreName());
        storeInfo.setStoreAddress(originalStoreInfo.getStoreAddress());
        storeInfo.setInBusiness(originalStoreInfo.getInBusiness());
        storeInfo.setIsDelete(originalStoreInfo.getIsDelete());
        storeInfo.setStorePhone(originalStoreInfo.getStorePhone());
        storeInfo.setUpdateTime(originalStoreInfo.getUpdateTime());
        storeInfo.setRegisterTime(originalStoreInfo.getRegisterTime());
        storeInfo.setFeaturesInfo(originalStoreInfo.getFeaturesInfo());
        storeInfo.setBusinessTime(originalStoreInfo.getBusinessTime());
        return storeInfo;
    }
}